#include "rfid_api.h"
#include "iso14443a.h"

#if _RFID_FUNCTION_ENABLE_

uint8_t TypeAHalt(void)
{
  uint8_t SnrCheck = 0;
  uint16_t RxDataLength = 0;
  uint8_t OperationDataBuff[MAXRLEN] = {0};

  OperationDataBuff[0] = PICC_HALT;
  OperationDataBuff[1] = 0;

  RfidPcdWriteReg(JREG_BITFRAMING, 0x00);
  RfidPcdSetBitMask(JREG_TXMODE, 0x80);
  RfidPcdSetBitMask(JREG_RXMODE, 0x80);

  RfidPcdSetTimer(1);
  RfidPcdCommunication(PCD_TRANSCEIVE, OperationDataBuff, 2, OperationDataBuff, &RxDataLength);

  return MI_OK;
}

uint8_t TypeAWakeUp(void)
{
  return MI_ERR;
}

uint8_t TypeARequest(uint8_t RequestCode, uint8_t *pTagType)
{
  uint16_t RxDataLength = 0;
  uint8_t RequestStatus = MI_ERR;
  uint8_t OperationDataBuff[MAXRLEN] = {0};

  RfidPcdClearBitMask(JREG_TXMODE, 0x80);
  RfidPcdClearBitMask(JREG_RXMODE, 0x80);
  RfidPcdClearBitMask(JREG_STATUS2, 0x08);

  RfidPcdWriteReg(JREG_BITFRAMING, 0x07);
  OperationDataBuff[0] = RequestCode;
  RfidPcdSetTimer(1);

  RequestStatus = RfidPcdCommunication(PCD_TRANSCEIVE, OperationDataBuff, 1, OperationDataBuff, &RxDataLength);
  if ((RequestStatus == MI_OK) && (RxDataLength == 0x10))
  {
    if (pTagType != NULL)
    {
      *pTagType = OperationDataBuff[0];
      *(pTagType + 1) = OperationDataBuff[1];
    }

    return MI_OK;
  }

  return MI_ERR;
}

uint8_t TypeAAnticollision(uint8_t *pSnr)
{
  uint16_t RxDataLength = 0;
  uint8_t OperationDataBuff[MAXRLEN] = {0};
  uint8_t SnrCheck = 0, AnticollResult = MI_ERR;

  if (pSnr != NULL)
  {
    RfidPcdClearBitMask(JREG_TXMODE, 0x80);
    RfidPcdClearBitMask(JREG_RXMODE, 0x80);
    RfidPcdClearBitMask(JREG_STATUS2, 0x08);
    RfidPcdWriteReg(JREG_BITFRAMING, 0x00);
    RfidPcdWriteReg(JREG_COLL, 0x80);

    OperationDataBuff[0] = PICC_ANTICOLL1;
    OperationDataBuff[1] = 0x20;

    RfidPcdSetTimer(1);
    AnticollResult = RfidPcdCommunication(PCD_TRANSCEIVE, OperationDataBuff, 2, OperationDataBuff, &RxDataLength);
    if (AnticollResult == MI_OK)
    {
      for (uint8_t i = 0; i < 5; i++)
      {
        *(pSnr + i) = OperationDataBuff[i];
      }

      if (pSnr[4] == (pSnr[0] ^ pSnr[1] ^ pSnr[2] ^ pSnr[3]))
        return MI_OK;

      if (SnrCheck != OperationDataBuff[4])
        return MI_ERR;
    }
  }

  return AnticollResult;
}

uint8_t TypeASelect(uint8_t *pSnr)
{
  uint16_t RxDataLength = 0;
  uint8_t SelectResult = MI_ERR;
  uint8_t OperationDataBuff[MAXRLEN] = {0};

  if (pSnr != NULL)
  {
    RfidPcdWriteReg(JREG_BITFRAMING, 0x00);
    RfidPcdSetBitMask(JREG_TXMODE, 0x80);
    RfidPcdSetBitMask(JREG_RXMODE, 0x80);
    RfidPcdClearBitMask(JREG_STATUS2, 0x08);

    OperationDataBuff[0] = PICC_ANTICOLL1;
    OperationDataBuff[1] = 0x70;

    for (uint8_t i = 0; i < 5; i++)
    {
      OperationDataBuff[i + 2] = *(pSnr + i);
    }

    RfidPcdSetTimer(1);
    SelectResult = RfidPcdCommunication(PCD_TRANSCEIVE, OperationDataBuff, 7, OperationDataBuff, &RxDataLength);
  }

  return SelectResult;
}

bool TypeAAuthenticate(uint8_t *pCardSn)
{
  if (TypeARequest(PICC_REQALL, NULL) == MI_OK)
  {
    if (TypeAAnticollision(pCardSn) == MI_OK)
    {
      if (TypeASelect(pCardSn) == MI_OK)
        return true;
    }
  }

  return false;
}

#endif
